﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using TransitionEffects;

namespace JizCode.WPF
{
    public class ActivityHost : Grid
    {
        Grid _effectContainer;
        Image _oldChild;
        Image _currentChild;

        Grid _container;
        private List<Activity> _activities = new List<Activity>();

        private bool _isSwitching = false;
        private Activity _oldActivity;
        private Activity _currentActivity;

        public ActivityHost()
        {
            _container = new Grid();
            this.Children.Add(_container);

            _effectContainer = new Grid();
            _oldChild = new Image();
            _oldChild.Stretch = System.Windows.Media.Stretch.None;
            _currentChild = new Image();
            _currentChild.Stretch = System.Windows.Media.Stretch.None;
            _effectContainer.Children.Add(_oldChild);
            _effectContainer.Children.Add(_currentChild);
            this.Children.Add(_effectContainer);
        }

        public void Switch(Activity activity)
        {
            if (_isSwitching)
            {
                return;
            }

            _isSwitching = true;
            if (_activities.Count > 0)
            {
                _oldActivity = _activities.LastOrDefault();
                _currentActivity = activity;
                activity.ActivityHost = this;
                _container.Children.Add(activity);
                activity.Loaded += activity_Loaded;
            }
            else
            {
                _effectContainer.Visibility = System.Windows.Visibility.Hidden;
                activity.ActivityHost = this;
                _container.Children.Add(activity);
                _activities.Add(activity);
                activity.Active();

                _isSwitching = false;
            }
        }

        public void Back()
        {
            if (_isSwitching)
            {
                return;
            }
            if (_activities.Count > 1)
            {
                _isSwitching = true;

                _oldActivity = _activities.LastOrDefault();
                _currentActivity = _activities[_activities.Count - 2];
                ApplyTransitionEffect(false, _oldActivity, _currentActivity, BackTransitionCompleted);
            }
        }

        void activity_Loaded(object sender, System.Windows.RoutedEventArgs e)
        {
            _activities.Add(_currentActivity);
            ApplyTransitionEffect(true, _oldActivity, _currentActivity, SwitchTransitionCompleted);
        }

        private void ApplyTransitionEffect(bool isNext, Activity oldVisual, Activity newVisual, EventHandler handler)
        {
            _effectContainer.Visibility = System.Windows.Visibility.Visible;
            int width = (int)this.ActualWidth;
            int height = (int)this.ActualHeight;
            Debug.WriteLine(string.Format("{0},{1}", width, height));
            RenderTargetBitmap RenderBmp = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
            RenderBmp.Render(newVisual);
            this._currentChild.Source = RenderBmp;

            RenderTargetBitmap RenderBmp2 = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
            RenderBmp2.Render(oldVisual);
            this._oldChild.Source = RenderBmp2;

            this._oldChild.Effect = null;

            TransitionEffect[] effectGroup = new TransitionEffect[]
            {
                new SlideInTransitionEffect{ SlideAmount= new Point(1, 0)},
                new SlideInTransitionEffect{ SlideAmount=new Point(-1, 0)}
            };
            TransitionEffect effect = null;
            if (isNext)
            {
                effect = effectGroup[0];
            }
            else
            {
                effect = effectGroup[1];
            }

            DoubleAnimation da = new DoubleAnimation(0.0, 1.0, new Duration(TimeSpan.FromSeconds(1.0f)), FillBehavior.HoldEnd);
            da.EasingFunction = new ExponentialEase();
            da.Completed += new EventHandler(handler);
            effect.BeginAnimation(TransitionEffect.ProgressProperty, da);

            VisualBrush vb = new VisualBrush(this._oldChild);
            vb.Viewbox = new Rect(0, 0, width, height);//this._oldChild.ActualWidth, this._oldChild.ActualHeight);
            //Debug.WriteLine(string.Format("oldchild {0},{1}", this._oldChild.ActualWidth, this._oldChild.ActualHeight));
            vb.ViewboxUnits = BrushMappingMode.Absolute;

            ////this.oldChild.Width = this.oldChild.ActualWidth;
            ////this.oldChild.Height = this.oldChild.ActualHeight;
            ////this.oldChild.Measure(new Size(this.oldChild.ActualWidth, this.oldChild.ActualHeight));
            ////this.oldChild.Arrange(new Rect(0, 0, this.oldChild.ActualWidth, this.oldChild.ActualHeight));

            effect.OldImage = vb;
            this._currentChild.Effect = effect;
        }

        private void SwitchTransitionCompleted(object sender, EventArgs e)
        {
            this._currentChild.Effect = null;
            _effectContainer.Visibility = System.Windows.Visibility.Hidden;

            _oldActivity.Deactive();
            _oldActivity.Destory();
            _currentActivity.Active();
            _oldActivity = null;
            _currentActivity = null;

            Debug.WriteLine("switch finish");
            _isSwitching = false;
        }

        private void BackTransitionCompleted(object sender, EventArgs e)
        {
            this._currentChild.Effect = null;
            _effectContainer.Visibility = System.Windows.Visibility.Hidden;

            _oldActivity.Deactive();
            _currentActivity.Active();
            _activities.Remove(_oldActivity);
            _container.Children.Remove(_oldActivity);
            _oldActivity = null;
            _currentActivity = null;
            Debug.WriteLine("switch finish");
            _isSwitching = false;
        }
    }
}
